﻿#define pai 3.14
#include <iostream>
#include<assert.h>
#include<stdio.h>
#include<easyx.h>
#include<Wingdi.h>
#include<ctype.h>
#include<limits.h>
//简单图形的实现！
//int main()
//{
//	initgraph(800, 600);		//initgraph设置画布的大小！
//	setaspectratio(1, -1);		//setsapectratio设置坐标缩放比例！
//	setorigin(400, 300);		//setorigin设置逻辑坐标轴原点的位置！
//	//for (int r = 0; r < 300; r += 30)
//	//{
//	//	circle(0, 0, r);
//	//	getchar();
//	//}
//	//circle(0,0, 300);			//circle函数画出一个圆（x,y,半径！）
//
//	int x, y;
//	/*for (int i = 0; i < 1000; i++)
//	{
//		x = rand() % (800 + 1) - 400;
//		y = rand() % (600 + 1) - 300;
//		putpixel(x, y, RED);
//	}		*/					//putpixel函数用来画出一个点！
//
//	//绘制一条线
//	/*line(100, 100, 200, 200);*/	//line 函数用来绘制一条线，两个参数一对，第一对参数为起始点的坐标，
//								//后面一对为结束点的坐标！
//
//	//绘制矩形
//	//rectangle(-200, 100, 200, -100);		//rectangle函数只需要知道左上角和右下角的顶点坐标即可绘制出矩形！
//	//ellipse(-200, 100, 200, -100);			//ellipse函数是画出椭圆，前两个是左上角的椭圆外切矩形的坐标，后面是右下角的坐标!
//	//roundrect(-200, 100, 200, -100, 200, 100);//绘制圆角矩形，后面两个参数是圆角矩形的宽和高！
//	/*pie(-200, 100, 200, -100, 0, pai / 4);	*/	//pie函数用来绘制一个扇形，前四个参数仍然是其外切矩形的左上角和右下角坐标
//												//最后两个参数分别是开始的弧度和结束的弧度，顺时针为正！
//	arc(-200, 100, 200, -100, 0, pai / 4);		//arc函数是绘制一段圆弧，与pie扇形参数相同，不同的是它只会绘画其中的一段！
//	getchar();					//防止画布直接消失！
//	closegraph();				//关闭画布！
//	return 0;
//
//}
//


//用宏实现offsteof
//struct stu
//{
//	int a = 0;
//	char b = 0;
//	char c = 0;
//};
//#define OFFSTEOF(type,name)         &(((type*)0)->name)
//#include<stdio.h>
//int main()
//{
//	//printf("%d\n",offsetof(struct stu, a));
//	//printf("%d\n",offsetof(struct stu, b));
//	//printf("%d\n",offsetof(struct stu, c));
//
//
//
//
//	printf("%d\n", OFFSTEOF(struct stu, a));
//	printf("%d\n", OFFSTEOF(struct stu, b));
//	printf("%d\n", OFFSTEOF(struct stu, c));
//	return 0;
//}


//交换一个数的奇数位和偶数位！
//假设第一位从1开始！
//分别保留其奇数位和偶数位，然后让奇数位向左移动一位，偶数位向右移动一位!
//然后将移动后的奇数位和偶数位相加即可！
//1 0 1 0 0 0 1 1 1 0 
//		0 0 0 1 0 0  
// 0101
// 1010
//所求数字与0x55 55 55 55  进行与运算！得到的是奇数位！
//所求的数字0xaa aa aa aa  进行与运算！得到的是偶数位！
//int main()
//{
//	//奇数位
//	int n = 5;
//	int i = 0;
//	int j = 0;
//	int ou = 0;
//	j = n & 0x55555555;
//	ou = n & 0xaaaaaaaa;
//	//然后让奇数位左移一位
//	j = j << 1;
//	ou = ou >> 1;
//	n = j + ou;
//	printf("%d", n);
//}


//模拟实现atoi
//atoi的作用是将一个字符串转化为一个数字！
//enum station
//{
//	VALID,
//	INVALID
//};
//enum station s = INVALID;
//int my_atoi(char* ptr)
//{
//	//解决了传递的是空指针的问题！
//	assert(ptr); 
//	int flag = 0;
//	if (*ptr == '\0')
//	{
//		return 0;
//	}
//	if (*ptr=='+')
//	{
//		flag= 1;
//		ptr++;
//	}
//	else if (*ptr == '-')
//	{
//		flag= -1;
//		ptr++;
//	}
//	long long ret = 0;
//	while (*ptr)
//	{
//		if (isdigit(*ptr))
//		{
//			ret = ret * 10 + flag * (*ptr - '0');
//			if (ret > INT_MAX || ret < INT_MIN)
//			{
//				return (int)ret;
//			}
//		}
//		else
//			{
//				return (int)ret;
//			}
//			ptr++;
//	}
//	if (*ptr == '\0')
//	{
//		s = VALID;
//	}
//	return (int)ret;
//}
//int main()
//{
//	char arr[] = "123dd";
//	int ch = my_atoi(arr);
//	if (s == INVALID)
//	{
//		printf("转化非法：%d\n", ch);
//	}
//	else
//	{
//		printf("转化合法：%d\n", ch);
//	}
//	return 0;
//}

//显然次模拟实现没有考虑到是否传递的是空指针的问题！
//还有是否传递的是空字符串！
//传递的是正负数的问题！
//传递的是否出现越界的问题！


#include<assert.h>
enum station
{
	VALID,
	INVALID
}s;

int my_atoi(char* ptr)
{
	s = INVALID;		//因为大多数都是非法转化情况，所以一开始将默认状态为非法的！
	//空指针的问题!
	assert(*ptr);
	//空字符串的问题！
	if (*ptr == '\0')
	{
		return 0;
	}
	//正负号的问题
	int flag = 0;
	if (*ptr == '+')
	{
		flag = 1;
		ptr++;
	}
	else if (*ptr == '-')
	{
		flag = -1;
		ptr++;
	}

	//是否出现溢出问题！
	long long ret = 0;
	while (*ptr)
	{
		if (isdigit(*ptr))
		{
			ret = ret * 10 + flag * (*ptr - '0');
			ptr++;
			if (ret > INT_MAX || ret < INT_MIN)
			{
				return (int)ret;
			}
		}
		else
		{
			return (int)ret;
		}
	}
	if (*ptr == '\0')
	{
		s= VALID;
	}
	return ret;
}
int main()
{
	char arr[] = " ";
	int ch = my_atoi(arr);
	if (s = VALID)
	{
		printf("转化合法：%d", ch);
	}
	else
	{
		printf("转化非法：%d",ch);
	}

	return 0;
}